package com.benefm.multipar.pad.ble;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.benefm.multipar.pad.BaseApp;
import com.benefm.multipar.pad.R;
import com.benefm.multipar.pad.databinding.ActivityEcgWaveBleBinding;
import com.benefm.multipar.pad.event.AtmosphericPressure;
import com.benefm.multipar.pad.event.BloodPressureEvent;
import com.benefm.multipar.pad.event.CarbonDioxideEvent;
import com.benefm.multipar.pad.event.EventAction;
import com.benefm.multipar.pad.event.GyroscopeInfoEvent;
import com.benefm.multipar.pad.event.HrBatteryEvent;
import com.benefm.multipar.pad.event.LatLngEvent;
import com.benefm.multipar.pad.event.MsgEvent;
import com.benefm.multipar.pad.util.resp.BrAlgorithm;
import com.benefm.multipar.pad.view.EcgWaveData;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class EcgWaveBleActivity extends AppCompatActivity {

    protected ActivityEcgWaveBleBinding binding;

    protected final ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);

    public static final int N = 125;
    protected float[] hfDataI = new float[N];
    protected float[] hfDataII = new float[N];
    protected float[] hfDataIII = new float[N];
    protected float[] hfDataAvr = new float[N];
    protected float[] hfDataAvl = new float[N];
    protected float[] hfDataAvf = new float[N];
    protected float[] hfDataV1 = new float[N];
    protected float[] hfDataV2 = new float[N];
    protected float[] hfDataV3 = new float[N];
    protected float[] hfDataV4 = new float[N];
    protected float[] hfDataV5 = new float[N];
    protected float[] hfDataV6 = new float[N];

    private int hfPtrI = 0, hfPtrII = 0, hfPtrIII = 0, hfPtrAvr = 0, hfPtrAvl = 0, hfPtrAvf = 0,
            hfPtrV1 = 0, hfPtrV2 = 0, hfPtrV3 = 0, hfPtrV4 = 0, hfPtrV5 = 0, hfPtrV6 = 0;
    private float hfyI = 0, hfyII = 0, hfyIII = 0, hfyAvr = 0, hfyAvl = 0, hfyAvf = 0,
            hfyV1 = 0, hfyV2 = 0, hfyV3 = 0, hfyV4 = 0, hfyV5 = 0, hfyV6 = 0;

    private Vector<Integer> hrArray = new Vector<>();
    private Integer count = 0;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_ecg_wave_ble);

        EventBus.getDefault().register(this);

        binding.textBattery.setVisibility(BaseApp.isDebug ? View.VISIBLE : View.GONE);
        binding.imagePosture.setVisibility(View.INVISIBLE);

        executor.scheduleAtFixedRate(() -> {
            List<Short> data = BLEManager.getInstance().respData;
            ArrayList<Integer> list = new ArrayList<>();
            for (int i = 0; i < data.size(); i++) {
                list.add(Integer.parseInt(String.valueOf(data.get(i))));
            }
            BrAlgorithm brAlgorithm = new BrAlgorithm();
            int resp = brAlgorithm.calcBR(list, 250);
            if (resp > 0) {
                runOnUiThread(() -> binding.textBreath.setText(String.valueOf(resp)));
            }
            System.out.println("============== resp is " + resp + ",list size =" + list.size());
        }, 5, 5, TimeUnit.SECONDS);

    }


    @SuppressLint({"DefaultLocale", "SetTextI18n"})
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMsgEvent(MsgEvent event) {
        if (EventAction.ECG_DATA_LEAD_I == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(0, convertData(0, f)));
            }
            binding.ecgView.notifyData0(data);
        } else if (EventAction.ECG_DATA_LEAD_II == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(1, convertData(1, f)));
            }
            binding.ecgView.notifyData1(data);
        } else if (EventAction.ECG_DATA_LEAD_III == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(2, convertData(2, f)));
            }
            binding.ecgView.notifyData2(data);
        } else if (EventAction.ECG_DATA_LEAD_AVR == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(3, convertData(3, f)));
            }
            binding.ecgView.notifyData3(data);
        } else if (EventAction.ECG_DATA_LEAD_AVL == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(4, convertData(4, f)));
            }
            binding.ecgView.notifyData4(data);
        } else if (EventAction.ECG_DATA_LEAD_AVF == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(5, convertData(5, f)));
            }
            binding.ecgView.notifyData5(data);
        } else if (EventAction.ECG_DATA_LEAD_V1 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(6, convertData(6, f)));
            }
            binding.ecgView.notifyData6(data);
        } else if (EventAction.ECG_DATA_LEAD_V2 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(7, convertData(7, f)));
            }
            binding.ecgView.notifyData7(data);
        } else if (EventAction.ECG_DATA_LEAD_V3 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(8, convertData(8, f)));
            }
            binding.ecgView.notifyData8(data);
        } else if (EventAction.ECG_DATA_LEAD_V4 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(9, convertData(9, f)));
            }
            binding.ecgView.notifyData9(data);
        } else if (EventAction.ECG_DATA_LEAD_V5 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(10, convertData(10, f)));
            }
            binding.ecgView.notifyData10(data);
        } else if (EventAction.ECG_DATA_LEAD_V6 == event.getAction()) {
            ArrayList<EcgWaveData> data = new ArrayList<>();
            List<Short> list = (List<Short>) event.getT();
            for (short f : list) {
                data.add(new EcgWaveData(11, convertData(11, f)));
            }
            binding.ecgView.notifyData11(data);
        } else if (EventAction.DEVICE_ECG_HR == event.getAction()) {
            int hr = (int) event.getT();
            binding.textHr.setText(String.valueOf(hr));
        } else if (EventAction.DEVICE_BLOOD_PRESSURE == event.getAction()) {
            BloodPressureEvent bpEvent = (BloodPressureEvent) event.getT();
            binding.textDp.setText(bpEvent.sbp + "/" + bpEvent.dbp);
            binding.textPr.setText(String.valueOf(bpEvent.pr));
        } else if (EventAction.DEVICE_SPO2 == event.getAction()) {
            int spo2 = (int) event.getT();
            binding.textSpo2.setText(String.valueOf(spo2));
        } else if (EventAction.DEVICE_SPO2_INVALID == event.getAction()) {
            binding.textSpo2.setText("--");
        } else if (EventAction.DEVICE_GYROSCOPE == event.getAction()) {
            binding.imagePosture.setVisibility(View.VISIBLE);
            GyroscopeInfoEvent infoEvent = (GyroscopeInfoEvent) event.getT();
            if (infoEvent.degrees > 70.0) {
                binding.imagePosture.setImageResource(R.drawable.ic_baseline_fall);
//                binding.textPosture.setText("跌倒");
//                binding.textPosture.setTextColor(getResources().getColor(R.color.orange));
            } else {
                binding.imagePosture.setImageResource(R.drawable.ic_baseline_stand);
//                binding.textPosture.setText("站立");
//                binding.textPosture.setTextColor(getResources().getColor(R.color.black9));
            }

        } else if (EventAction.DEVICE_RESP_DATA == event.getAction()) {
            int resp = (int) event.getT();
            binding.textBreath.setText(String.valueOf(resp));

        } else if (EventAction.DEVICE_TEMPERATURE == event.getAction()) {
            int temp = (int) event.getT();
//            binding.textTemp.setText(new DecimalFormat("0.0").format(temp / 100f));
            binding.textTemp.setText(String.format("%.1f", temp / 100f));
        } else if (EventAction.DEVICE_TEMPERATURE_INVALID == event.getAction()) {
            binding.textTemp.setText("--");
        } else if (EventAction.ECG_HR_BATTERY == event.getAction()) {
            HrBatteryEvent model = (HrBatteryEvent) event.getT();
            binding.textBattery.setText(model.battery + "%");
            if (model.hr < 30 || model.hr > 300) {
                binding.textHr.setText("NA");
            } else {
//                binding.textHr.setText(String.valueOf(model.hr));
                if (hrArray.size() == 6) {
                    Collections.sort(hrArray);
                    int mHr = (hrArray.get(2) + hrArray.get(3)) / 2;
                    binding.textHr.setText(String.valueOf(mHr));
                    hrArray.set(count, model.hr);
                    count++;
                    if (count == 6) count = 0;
                } else if (hrArray.size() < 6) {
                    hrArray.add(model.hr);
                }
            }
        } else if (EventAction.DEVICE_BPW1_PRESSURE == event.getAction()) {
            int pressureValue = (int) event.getT();
            binding.textDp.setText(String.valueOf(pressureValue));
            binding.textDp.setTextSize(20f);
            binding.textDp.setTextColor(getResources().getColor(R.color.black9));
        } else if (EventAction.DEVICE_BPW1_SBP_DBP == event.getAction()) {
            BloodPressureEvent bpEvent = (BloodPressureEvent) event.getT();
            binding.textDp.setTextSize(20f);
            binding.textDp.setTextColor(getResources().getColor(R.color.black9));
            binding.textDp.setText(bpEvent.sbp + " / " + bpEvent.dbp);
            binding.textPr.setText(String.valueOf(bpEvent.pr));
        } else if (EventAction.DEVICE_BPW1_ERROR == event.getAction()) {
            String errorMessage = (String) event.getT();
            binding.textDp.setText(errorMessage);
            binding.textDp.setTextSize(14f);
            binding.textDp.setTextColor(getResources().getColor(R.color.yellow));
        } else if (EventAction.DEVICE_TEMPERATURE_HUMIDITY == event.getAction()) {
            CarbonDioxideEvent dioxideEvent = (CarbonDioxideEvent) event.getT();
            boolean co2Invalid = dioxideEvent.value == 0 || dioxideEvent.value == 0xffff;
            binding.textCarbonDioxide.setText(co2Invalid ? "--" : String.valueOf(dioxideEvent.value));

            boolean tempInvalid = dioxideEvent.temp == 0 || dioxideEvent.temp == 0x8000;
            boolean humidityInvalid = dioxideEvent.humidity == 0 || dioxideEvent.temp == 0xffff;

            binding.textTempAndHumidity.setText((tempInvalid ? "--" : String.format("%.1f℃", dioxideEvent.temp / 10f)) + " / " +
                    (humidityInvalid ? "--" : (dioxideEvent.humidity + "%")));

        } else if (EventAction.DEVICE_ATMOSPHERIC_PRESSURE == event.getAction()) {
            AtmosphericPressure ap = (AtmosphericPressure) event.getT();
            binding.textAtmospheric.setText(String.format("%.2f", ap.value / 100f));
            binding.tempAndHumidity.setText(String.format("%.1f℃", ap.temp / 10f) + " / " + ap.humidity + "%");
        } else if (EventAction.DEVICE_LATITUDE_LONGITUDE == event.getAction()) {
            LatLngEvent latlng = (LatLngEvent) event.getT();
            if (TextUtils.isEmpty(latlng.lat) || TextUtils.isEmpty(latlng.lng))
                return;
            binding.textTrajectory.setText(latlng.lat + "\n" + latlng.lng);

        } else if (EventAction.DEVICE_DISCONNECTED == event.getAction()) {
            new AlertDialog.Builder(this)
                    .setMessage("设备连接已断开，请检查！")
                    .setPositiveButton("知道了", (dialog, which) -> {
                        dialog.dismiss();
                    })
                    .create()
                    .show();
        }

    }


    public float convertData(int index, Short data) {
        if (index == 0) {
            hfyI = hfyI + Float.parseFloat(String.valueOf(data)) - hfDataI[hfPtrI];
            int halfPtr = hfPtrI - N / 2;
            if (halfPtr < 0)
                halfPtr = halfPtr + N;
            float out = hfDataI[halfPtr] - (hfyI / N);
            hfDataI[hfPtrI] = data;
            hfPtrI = hfPtrI + 1;
            if (hfPtrI == N) {
                hfPtrI = 0;
            }
            return out;
        } else if (index == 1) {
            int halfPtr;
            hfyII = hfyII + Float.parseFloat(String.valueOf(data)) - hfDataII[hfPtrII];
            halfPtr = hfPtrII - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataII[halfPtr] - (hfyII / N);
            hfDataII[hfPtrII] = data;
            hfPtrII = hfPtrII + 1;
            if (hfPtrII == N) {
                hfPtrII = 0;
            }
            return out;
        } else if (index == 2) {
            int halfPtr;
            hfyIII = hfyIII + Float.parseFloat(String.valueOf(data)) - hfDataIII[hfPtrIII];
            halfPtr = hfPtrIII - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataIII[halfPtr] - (hfyIII / N);
            hfDataIII[hfPtrIII] = data;
            hfPtrIII = hfPtrIII + 1;
            if (hfPtrIII == N) {
                hfPtrIII = 0;
            }
            return out;
        } else if (index == 3) {
            int halfPtr;
            hfyAvr = hfyAvr + Float.parseFloat(String.valueOf(data)) - hfDataAvr[hfPtrAvr];
            halfPtr = hfPtrAvr - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataAvr[halfPtr] - (hfyAvr / N);
            hfDataAvr[hfPtrAvr] = data;
            hfPtrAvr = hfPtrAvr + 1;
            if (hfPtrAvr == N) {
                hfPtrAvr = 0;
            }
            return out;
        } else if (index == 4) {
            int halfPtr;
            hfyAvl = hfyAvl + Float.parseFloat(String.valueOf(data)) - hfDataAvl[hfPtrAvl];
            halfPtr = hfPtrAvl - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataAvl[halfPtr] - (hfyAvl / N);
            hfDataAvl[hfPtrAvl] = data;
            hfPtrAvl = hfPtrAvl + 1;
            if (hfPtrAvl == N) {
                hfPtrAvl = 0;
            }
            return out;
        } else if (index == 5) {
            int halfPtr;
            hfyAvf = hfyAvf + Float.parseFloat(String.valueOf(data)) - hfDataAvf[hfPtrAvf];
            halfPtr = hfPtrAvf - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataAvf[halfPtr] - (hfyAvf / N);
            hfDataAvf[hfPtrAvf] = data;
            hfPtrAvf = hfPtrAvf + 1;
            if (hfPtrAvf == N) {
                hfPtrAvf = 0;
            }
            return out;
        } else if (index == 6) {
            int halfPtr;
            hfyV1 = hfyV1 + Float.parseFloat(String.valueOf(data)) - hfDataV1[hfPtrV1];
            halfPtr = hfPtrV1 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV1[halfPtr] - (hfyV1 / N);
            hfDataV1[hfPtrV1] = data;
            hfPtrV1 = hfPtrV1 + 1;
            if (hfPtrV1 == N) {
                hfPtrV1 = 0;
            }
            return out;
        } else if (index == 7) {
            int halfPtr;
            hfyV2 = hfyV2 + Float.parseFloat(String.valueOf(data)) - hfDataV2[hfPtrV2];
            halfPtr = hfPtrV2 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV2[halfPtr] - (hfyV2 / N);
            hfDataV2[hfPtrV2] = data;
            hfPtrV2 = hfPtrV2 + 1;
            if (hfPtrV2 == N) {
                hfPtrV2 = 0;
            }
            return out;
        } else if (index == 8) {
            int halfPtr;
            hfyV3 = hfyV3 + Float.parseFloat(String.valueOf(data)) - hfDataV3[hfPtrV3];
            halfPtr = hfPtrV3 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV3[halfPtr] - (hfyV3 / N);
            hfDataV3[hfPtrV3] = data;
            hfPtrV3 = hfPtrV3 + 1;
            if (hfPtrV3 == N) {
                hfPtrV3 = 0;
            }
            return out;
        } else if (index == 9) {
            int halfPtr;
            hfyV4 = hfyV4 + Float.parseFloat(String.valueOf(data)) - hfDataV4[hfPtrV4];
            halfPtr = hfPtrV4 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV4[halfPtr] - (hfyV4 / N);
            hfDataV4[hfPtrV4] = data;
            hfPtrV4 = hfPtrV4 + 1;
            if (hfPtrV4 == N) {
                hfPtrV4 = 0;
            }
            return out;
        } else if (index == 10) {
            int halfPtr;
            hfyV5 = hfyV5 + Float.parseFloat(String.valueOf(data)) - hfDataV5[hfPtrV5];
            halfPtr = hfPtrV5 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV5[halfPtr] - (hfyV5 / N);
            hfDataV5[hfPtrV5] = data;
            hfPtrV5 = hfPtrV5 + 1;
            if (hfPtrV5 == N) {
                hfPtrV5 = 0;
            }
            return out;
        } else if (index == 11) {
            int halfPtr;
            hfyV6 = hfyV6 + Float.parseFloat(String.valueOf(data)) - hfDataV6[hfPtrV6];
            halfPtr = hfPtrV6 - N / 2;

            if (halfPtr < 0) {
                halfPtr = halfPtr + N;
            }
            float out = hfDataV6[halfPtr] - (hfyV6 / N);
            hfDataV6[hfPtrV6] = data;
            hfPtrV6 = hfPtrV6 + 1;
            if (hfPtrV6 == N) {
                hfPtrV6 = 0;
            }
            return out;
        }
        return 0f;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        executor.shutdownNow();
        BaseApp.getInstance().respData.clear();
        BLEManager.getInstance().disconnect();
        EventBus.getDefault().unregister(this);
    }

}
